.TITLE ACSUB .IDENT /03.01/ ; ; Copyright (c) 1995 by Mentec, Inc., U.S.A. ; All rights reserved ; ; ; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED ; OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE. ; ; M. S. FOX 18-OCT-78 ; ; MODIFIED FOR RSX-11M-PLUS VERSION 2.1 BY: ; ; B. KRISHNAMURTHY ; ; MODIFIED BY: ; ; J. W. BERZLE 07-SEP-83 03.00 ; ; JWB047 -- ADD BUGCHECK FACILITY AND ERROR CODES ; ; D. Carroll 18-Oct-1995 03.01 ; DC404 - Include PSECT statement to allow ICB pool to be ; expanded during sysgen ; ; ; CPU ACCOUNTING COMMON SUBROUTINES ; ; MACRO LIBRARY CALLS ; .MCALL ACNDF$,ABODF$,BGCK$A ACNDF$ ;DEFINE ACCOUNTING BLOCK OFFSETS ABODF$ ;TASK ABORT CODES ;DC404 .IIF DF,K$$DAS&I$$CBP, .PSECT EXEC1 ;DC404 ;+ ; **-$QTRAN-QUEUE ACCOUNTING TRANSACTION TO SYSLOG (USE DEFAULT UAB) ; **-$QTRN1-QUEUE ACCOUNTING TRANSACTION TO SYSLOG (USE SPECIFIED UAB) ; **-$QTRN2-QUEUE ACCOUNTNIG TRANSACTION TO SYSLOG (NO UAB, PACKET IS COMPLETE) ; **-$QACNT-QUEUE ACCOUNT BLOCK TO SYSLOG (THE BLOCK IS ALREADY IN SEC. POOL) ; ; THESE ROUTINES QUEUE ALL THE ACCOUNTING DATA PACKETS TO THE SYSLOG TASK ; FOR PROCESSING ; ; INPUTS: ; ; R0=VIRTUAL ADDRESS OF PACKET IN CALLING TASK'S SPACE ($QTRAN, ; $QTRN1, $QTRN2) ; R1=RELOCATION BIAS TO MAP UAB OR ACCOUNT BLOCK ($QTRN1, $QACNT) ; ; OUTPUTS: ; ; BF.ERR SET IN $ACNFE IF ALLOCATION FAILURE OR SYSLOG NOT ACTIVE ; ; REGISTERS R3, R4, R5 PRESERVED ; ;- .IF DF A$$CNT .ENABL LSB $QTRAN::MOV $TKTCB,R1 ;LOCATE CURRENT TASK MOV T.ACN(R1),R1 ;LOCATE TASK'S ACCOUNTING BLOCKS BNE $QTRN1 ;IF NE, THERE ARE ACCOUNTING BLOCKS RETURN ;NOTHING TO DO $QTRN2::CLR R1 ;THERE IS NO UAB $QTRN1::TST $SABPT ;IS ACCOUNTING ACTIVE BEQ 45$ ;IF EQ NO SAVNR ;SAVE R4, R5 MOV R3,-(SP) ;SAVE R3 CLR R4 ; BISB B.LEN(R0),R4 ;GET PACKET LENGTH MOV R1,-(SP) ;SAVE UAB ADDRESS MOV R4,R1 ;LENGTH ADD #77,R1 ;ROUND UP TO NEXT 32 WORD BLOCK ASH #-6,R1 ;CONVERT TO NUMBER OF 32 WORD BLOCKS MOV R0,R5 ;SAVE VIRTUAL PACKET ADDRESS IN TASK SPACE CALL $ALACC ;ALLOCATE SECONDARY POOL BCC 10$ ;IF CC SUCCESS TST (SP)+ ;POP UAB ADDRESS BR 40$ ;RETURN 10$: MOV R0,-(SP) ;SAVE ALLOCATED BLOCK'S ADDRESS MOV R5,R0 ;GET VIRTUAL PACKET ADDRESS CALL $RELOC ;RELOCATE PACKET TO APR6 SUB #20000,R2 ;CONVERT TO APR5 OFFSET MOV R4,R0 ;GET PACKET LENGTH IN BYTES MOV (SP),R3 ;APR MAPPING BIAS TO SECONDARY POOL BLOCK MOV #140000,R4 ;VIRTUAL ADDRESS OF DESTINATION BLOCK CALL $BLXIO ;COPY PACKET INTO SECONDARY POOL MOV (SP)+,R1 ;ADDRESS OF PACKET IN SECONDARY POOL MOV #KISAR5,R3 ;POINT TO APR5 MOV (R3)+,R5 ;SAVE CURRENT APR5 MAPPING MOV (R3),R4 ;SAVE CURRENT APR6 MAPPING MOV R1,(R3) ;MAP SECONDARY POOL NODE IN APR6 MOV (SP)+,-(R3) ;MAP UAB IN APR5 BEQ 20$ ;IF EQ, NO UAB MOV #B.HID+140000,R2 ;GET START OF ID INFO IN HEADER 15$: MOV -20000(R2),(R2)+ ;COPY WORD INTO SEC POOL CMP #B.HEND+140000,R2 ;ALL HEADER ID DATA COPIED? BHI 15$ ;IF HI NO 20$: MOV R5,(R3)+ ;RESTORE APR5 MAPPING MOV R4,(R3) ;RESTORE APR6 MAPPING BR 25$ ; $QACNT:: ; MOV R3,-(SP) ;SAVE R3 25$: MOV #B.TIM,R0 ;GET OFFSET TO TIME FIELD IN PACKET CALL $TMSTP ;TIME STAMP PACKET MOV #$SYLHD,R0 ;POINT TO LISTHEAD CALL $QSPIF ;INSERT PACKET AT END OF SYSLOG QUEUE BIT #BF.ERR!BF.STR,$ACNFE ;SHOULD SYSLOG BE UNSTOPPED BNE 30$ ;IF NE NO MOV $LOGPT,R0 ;GET SYSLOG TCB ADDRESS BEQ 50$ ;IF EQ, NOT INSTALLED BIT #TS.EXE,T.STAT(R0) ;IS SYSLOG ACTIVE BNE 50$ ;IF NE NO BIT #BF.SLR,$ACNFE ;IS SYSLOG ACTIVELY RUNNING BNE 30$ ;IF NE YES CALL $EXRQN ;UNSTOP SYSLOG 30$: 40$: MOV (SP)+,R3 ;RESTORE R3 45$: RETURN ; 50$: BIS #BF.ERR,$ACNFE ;INDICATE ACCOUNTING HAS STOPPED DUE TO ERROR BR 30$ ;RETURN .DSABL LSB ;+ ; **-$ALACC-ALLOCATE SECONDARY POOL FOR ACCOUNTING USE ; **-$ALTAB-ALLOCATE A TASK ACCOUNT BLOCK (TAB) ; ; THIS ROUTINE DOES ALL SECONDARY POOL ALLOCATIONS FOR ACCOUNTING. ; A CHECK IS MADE TO INSURE THAT ACCOUNTING ALWAYS LEAVES A CERTAIN ; AMOUNT OF SEC POOL AVAILABLE. THE ALLOCATION WILL FAIL IF THIS MINIMUM ; AMOUNT OF CANNOT BE LEFT AFTER THE ACCOUNTING ALLOCATION. IF AN ACCOUNTING ; ALLOCATION FAILS FOR ANY REASON, A TKTN MESSAGE WILL BE PRINTED ON CO: ; DESCRIBING WHAT TASK LOST ITS ACCOUNTING BLOCK. ; ; ; INPUTS: ; ; R1=SIZE OF BUFFER TO ALLOCATE IN 32 WORD BLOCKS ; R4=TCB ADDRESS OF TASK TO RECEIVE TAB ($ALTAB ONLY) ; ; OUTPUTS: ; ; C=0 ALLOCATION SUCCESSFUL ; R0=APR BIAS TO MAP ALLOCATED BLOCK ; R1=NUMBER OF BLOCKS ALLOCATED ; C=1 CANNOT DO ALLOCATION ; ; REGISTERS R4, R5 PRESERVED ; ;- .ENABL LSB $ALTAB::MOV #T.NTAF,-(SP) ;ERROR CODE FOR TAB ALLOCATION FAILURE BR 5$ ;JOIN COMMON CODE $ALACC::MOV #T.NAAF,-(SP) ;GENERAL ACCOUNTING ALLOCATION FAILURE 5$: BIT #BF.ERR,$ACNFE ;HAS THERE BEEN A FATAL ACCOUNTING ERROR BNE 10$ ;IF NE YES MOV $SECFR,R2 ;GET AMOUNT OF FREE SECONDARY POOL SUB R1,R2 ;ALLOW FOR THIS ALLOCATION CMP $APLIM,R2 ;WILL THERE BE ENOUGH LEFT AFTER IT BHI 10$ ;IF HI NO CALL $ALSEC ;ALLOCATE SECONDARY POOL BCS 10$ ;IF CS, ALLOCATION FAILURE TST (SP)+ ;THROW AWAY ERROR CODE RETURN ; 10$: MOV (SP)+,R0 ;GET ERROR CODE SAVNR ;SAVE R4, R5 CMP #T.NTAF,R0 ;IS IT A TAB ALLOCATION FAILURE BEQ 20$ ;IF EQ YES MOV $TKTCB,R4 ;LOCATE CURRENT TASK TCB 20$: MOV T.NAM(R4),R5 ;GET FIRST HALF OF TASK NAME MOV T.NAM+2(R4),R4 ;GET SECOND HALF CALL $DVMSG ;REQUEST TKTN SEC ;INDICATE ERROR RETURN .DSABL LSB ;+ ; **-$TMSTP-TIME STAMP AN ACCOUNTING BLOCK ; ; THIS ROUTINE COPIES THE CURRENT TIME FROM $TTNS INTO THE SPECIFIED ; OFFSET IN THE ACCOUNTING BLOCK IN SECONDARY POOL ; ; INPUTS: ; ; R0=OFFSET TO START OF 3 WORD TIME FIELD IN BLOCK ; R1=APR BIAS TO MAP ACCOUNTING BLOCK ; ; OUTPUTS: ; ; TIME FIELD OF BLOCK UPDATED ; ; REGISTERS R1, R3, R4, R5 PRESERVED ; ;- $TMSTP::MOV KISAR6,-(SP) ;SAVE APR6 MAPPING MOV R1,KISAR6 ;MAP ACCOUNTING BLOCK ADD #140000,R0 ;GET VIRTUAL ADDRESS OF TIME FIELD MOV #$TTNS-14,R2 ;POINT TO CURRENT TIME 10$: MOVB (R2)+,(R0)+ ;COPY FIELD INC R2 ;SKIP HIGH BYTE OF WORD FIELD IN SYSCM CMP #$TTNS,R2 ;COPYING COMPLETE? BHI 10$ ;IF HI NO MOV (SP)+,KISAR6 ;RESTORE MAPPING 20$: RETURN ; ;+ ; **-$CPUTM-CALCULATE CPU TIME USED BY A TASK ; **-$CPUT1-CALCULATE CPU TIME USED BY SPECIFIED TASK ; ; THIS ROUTINE CALCULATES THE AMOUNT OF CPU TIME A TASK HAS USED SINCE ; IT GOT CONTROL OF THE PROCESSOR. A VALUE OF ZERO IS ROUNDED UP TO ; 1/2 TICK BY COUNTING EVERY OTHER ZERO AS ONE TICK. THEREFORE A TASK ; WILL BE BILLED FOR AT LEAST 1/2 TICK EVERY TIME IT GETS CONTROL. ; ; INPUT: ; ; R0=TCB ADDRESS OF TASK TO BILL CPU TIME TO ($CPUT1 ONLY) ; NO INPUTS IF ENTRY AT $CPUTM ; ; OUTPUT: ; ; NONE ; ; REGISTERS R0, R1, R2, R3 MODIFIED ; ;- .ENABL LSB ; 10$: BGCK$A BF.ACC,BE.NCT,FATAL ;MUST BE ACTIVE TASK WITH ACCOUNTING ; $CPUTM::MOV $TKTCB,R0 ;LOCATE CURRENT TASK BEQ 10$ ;IF EQ, NO CURRENT TASK $CPUT1::MOV T.ACN(R0),R0 ;LOCATE TASK'S ACCOUNTING BLOCK BEQ 10$ ;IF EQ NO ACCOUNTING BLOCK INCB $BILNG ;END CPU BILLING PERIOD MOV $ACCLK+2,R2 ;GET LOW ORDER PART OF CURRENT TIME MOV $ACCLK,R3 ;GET HIGH ORDER PART SUB $STRTM+2,R2 ;CALCULATE TIME ELAPSED SINCE START SBC R3 ; SUB $STRTM,R3 ; MOV #B.CPU,R1 ;GET OFFSET TO CPU ACCUMULATION FIELD MOV R2,-(SP) ;CHECK IF DIFFERENCE IS ZERO BIS R3,(SP)+ ;CHECK BOTH HALFS OF NUMBER BNE 30$ ;IF NE, NON-ZERO MOV KISAR6,-(SP) ;SAVE CURRENT MAPPING BIT #BF.LSS,$ACNFE ;SYSTEM ACCONTING TURNED ON ? BEQ 15$ ;NO, IF EQ. MOV $SABPT,KISAR6 ;MAP SAB ADD #1,@#B.RND+140002 ;COUNT ZERO CPU INTERVAL ADC @#B.RND+140000 ;DOUBLE WORD COUNT 15$: MOV R0,KISAR6 ;MAP ACCOUNTING BLOCK BITB #BS.ZER,@#B.STM+140000 ;PREVIOUS ZERO INTERVAL? BNE 20$ ;IF NE YES BISB #BS.ZER,@#B.STM+140000 ;REMEMBER ZERO INTERVAL BR 50$ ; 20$: BICB #BS.ZER,@#B.STM+140000 ;RESET ZERO INDICATOR INC R2 ;COUNT A TICK, FOR 2 ZERO INTERVALS .IF DF X$$ACC&XA$$CT MOV (SP)+,KISAR6 ;RESTORE EXEC MAPPING 30$: MOV KISAR6,-(SP) ;SAVE EXEC MAPPING MOV $SABPT,KISAR6 ;MAP SAB MOV R4,-(SP) ;SAVE R4 .IF DF M$$PRO MOVB $PROC2,R4 ;GET PROCESSOR WORD INDEX ASL R4 ;MAKE IT A DBLWRD INDEX ADD #B.CPUT+140002,R4 ;POINT PAST ACCUMULATION BUCKET .IFF MOV #B.CPUT+140002,R4 ;POINT PAS ACCUMULATION BUCKET .ENDC ; DF M$$PRO ADD R2,(R4) ;ADD LOW ORDER CPU TIME FOR THIS PROCESSOR ADC -(R4) ; ADD R3,(R4) ;HIGH ORDER MOV (SP)+,R4 ;RESTORE R4 MOV (SP)+,KISAR6 ;RESTORE EXEC MAPPING .IFF BR 40$ ; 30$: ;ADD CPU TIME INTO ACCOUNTING BLOCKS .ENDC ;+ ; **-$ADATA-ADD DATA TO THE APPROPRIATE FIELD OF ACCOUNTING BLOCKS ; **-$ADATS-ADD DATA TO APPROPRIATE FIELD ASSUMING SINGLE PRECISION VALUE ; **-$ADAT1-INCREMENT THE APPROPRIATE ACCOUNTING ACCUMULATION FIELD ; ; THESE ROUTINES ADD THE SUPPLIED DATA TO THE ACCUMULATION FIELD OF EVERY ; ACCOUNTING BLOCK LINKED OFF THE INITIAL BLOCK UNTIL END OF THE LIST IS ; REACHED. A STANDARD TWO WORD ACCUMULATION FIELD IS REQUIRED. ; ; INPUTS: ; ; R0=APR BIAS TO MAP FIRST BLOCK IN LIST ; R1=OFFSET TO ACCUMULATION FIELD WITHIN BLOCK ; R2=LOW ORDER PART OF TO ADD ($ADATA, $ADATS ONLY) ; R3=HIGH ORDER PART OF VALUE ($ADATA ONLY) ; ; OUTPUTS: ; ; NONE ; ; ALL REGISTERS ARE PRESERVED ($ADAT1 DESTROYES R2) ; ;- $ADATA::MOV KISAR6,-(SP) ;SAVE CURRENT MAPPING MOV R0,KISAR6 ;MAP SUPPLIED INITIAL BLOCK 40$: ADD R2,140002(R1) ;ADD VALUE MOV R3,-(SP) ;GET HIGH ORDER PART OF VALUE ADC (SP) ;INCLUDE CARRY BIT FROM PREVIOUS ADD ADD (SP)+,140000(R1) ;ADD HIGH ORDER PART OF VALUE BCC 45$ ;IF CC, OK CALL OVFLW ;HANDLE OVERFLOW 45$: MOV @#B.PNT+140000,KISAR6 ;MAP NEXT BLOCK IN LIST BNE 40$ ;IF NE, THERE IS ONE 50$: MOV (SP)+,KISAR6 ;RESTORE MAPPING RETURN $ADAT1::MOV #1,R2 ;VALUE TO ADD $ADATS::MOV R3,-(SP) ;SAVE R3 CLR R3 ;MAKE HIGH ORDER PART OF VALUE ZERO CALL $ADATA ;CALL ADDITION ROUTINE MOV (SP)+,R3 ;RESTORE R3 RETURN .DSABL LSB ;+ ; **-OVFLW-HANDLE FIELD OVERFLOW FOR $ADATA ROUTINE ; ; THIS LOCAL ROUTINE GETS CALLED WHEN THE ADD, ADC, ADD SEQUENCE ; IN THE $ADATA ROUTINE RESULTS IN C=1 OUT OF THE SECOND ADD. ; IF THE ACCOUNTING BLOCK IS A TAB AND THE FIELD IS B.CPU, THE ; TASK HAS EXCEEDED ITS TIME LIMIT. IT IS THEREFORE ABORTED, UNLESS ; IT HAS ALREADY BEEN DEACTIVATED. THIS CAN HAPPEN BY THE CALL ; TO $CPUTM OUT OF DREIF. ; ; INPUTS: ; ; R1=OFFSET TO FIELD IN ACCOUNTING BLOCK ; ; THE ACCOUNTING BLOCK MUST BE MAPPED THROUGH KISAR6 ; ; OUTPUTS: ; ; NONE ; ;- OVFLW: CMPB #BT.TAB,@#B.TYP+140000 ;IS THIS A TASK ACCOUNT BLOCK BNE 20$ ;IF NE NO CMP #B.CPU,R1 ;IS CPU TIME BEING ACCUMULATED BNE 20$ ;IF NE NO MOV @#B.TCB+140000,R1 ;GET TCB ADDRESS OF TASK TST T.STAT(R1) ;IS TASK ACTIVE BMI 10$ ;IF MI NO MOV R0,-(SP) ;SAVE ORIGINAL ACCOUNTING BLOCK ADDRESS MOV #S.COTL,R0 ;SET ABORT CODE OF OVER TIME LIMIT MOV R2,-(SP) ;SAVE CPU TIME TO BE ADDED MOV R3,-(SP) ; CALL $ABTSK ;ABORT TASK MOV (SP)+,R3 ;RESTORE R3 MOV (SP)+,R2 ; MOV (SP)+,R0 ; 10$: MOV #B.CPU,R1 ;RESTORE OFFSET TO FIELD 20$: RETURN ; ;+ ;**-$ACINP-INCREMENT PROCESSOR SPECIFIC FIELD IN THE SAB ;**-$ACINC-INCREMENT FIELD IN SAB ; ; THESE TWO ROUTINES WILL INCREMENT A FIELD IN THE SAB. IF ENTRY ; IS AT $ACINP, THEN THE FIELD IS INDEXED BY THE PROCESSOR NUMBER. ; ; INPUTS: ; ; R0 = SAB OFFSET TO INCREMENT + 140002 ; (SP) = RETURN ADDRESS OF CALLER ; 2(SP) = SAVED R0 PRIOR TO LOADING OFFSET ; ; OUTPUTS: ; ; R0 IS RESTORED FROM PREVIOUS VALUE, STACK CLEANED ;- .IF DF X$$ACC $ACINP:: ;REFERENCE LABEL .IF DF M$$PRO MOV R0,-(SP) ;SAVE OFFSET INTO SAB MOVB $PROC2,R0 ;GET PROCESSOR WORD INDEX ASL R0 ;MAKE IT DOUBLEWORD ADD (SP)+,R0 ;ADJUST OFFSET .ENDC ; DF M$$PRO $ACINC::MOV KISAR6,-(SP) ;SAVE APR 6 MOV $SABPT,KISAR6 ;POINT TO SYSTEM ACCOUNT BLOCK BEQ 10$ ;IF EQ THERE IS NONE, RESTORE AND RETURN ADD #1,(R0) ;INCREMENT LOW HALF OF COUNT ADC -(R0) ;AND HIGH HALF IF APPROPRIATE 10$: MOV (SP)+,KISAR6 ;RESTORE EXEC MAPPING MOV (SP)+,R0 ;RESTORE RETURN ADDRESS RTS R0 ;RESTORE R0 AND RETURN TO USER .IFF ;X$$ACC $ACINP:: $ACINC:: .ENDC ;X$$ACC .IFF $QTRAN:: $QTRN1:: $QTRN2:: $QACNT:: $ALACC:: $TMSTP:: $CPUTM:: $CPUT1:: $ALTAB:: $ACINP:: $ACINC:: .ENDC .END